#ifndef _SK_MEDIADMC_H_
#define _SK_MEDIADMC_H_

/*----------------------------------------------------------------------
|   includes
+---------------------------------------------------------------------*/
#include "PltMediaServer.h"
#include "PltSyncMediaBrowser.h"
#include "PltMediaController.h"
#include "NptMap.h"
#include "NptStack.h"
/*----------------------------------------------------------------------
 |   definitions
 +---------------------------------------------------------------------*/
typedef NPT_Map<NPT_String, NPT_String>        PLT_StringMap;
typedef NPT_Lock<PLT_StringMap>                PLT_LockStringMap;
typedef NPT_Map<NPT_String, NPT_String>::Entry PLT_StringMapEntry;

/*----------------------------------------------------------------------
 |   PLT_SkMediaController
 +---------------------------------------------------------------------*/
class PLT_SkMediaController : public PLT_SyncMediaBrowser,
	public PLT_MediaController,
	public PLT_MediaControllerDelegate {
public:
	PLT_SkMediaController(PLT_CtrlPointReference &ctrlPoint);
	virtual ~PLT_SkMediaController();

	// PLT_MediaBrowserDelegate methods
	bool OnMSAdded(PLT_DeviceDataReference &device);
	void OnMSRemoved(PLT_DeviceDataReference &device);

	// PLT_MediaControllerDelegate methods
	bool OnMRAdded(PLT_DeviceDataReference &device);
	void OnMRRemoved(PLT_DeviceDataReference &device);
	void OnBrowseResult(NPT_Result               res, 
        			    PLT_DeviceDataReference& device, 
        			    PLT_BrowseInfo*          info, 
       			    	void*                   userdata);
	void OnSearchResult(NPT_Result               res, 
        			    PLT_DeviceDataReference& device, 
        			    PLT_BrowseInfo*          info, 
       			    	void*                   userdata);
	void OnBookOrRecordEventResult(NPT_Result res, 
        			    		PLT_DeviceDataReference& device, 
        			    		ActionMessage*          actionMessage, 
       			    			void*                    userdata);
	void OnMRStateVariablesChanged(PLT_Service  *service,
								   NPT_List<PLT_StateVariable *> *vars);
	void OnMSStateVariablesChanged(PLT_Service*                  service, 
                                                NPT_List<PLT_StateVariable*>* vars);
	NPT_String getAllRenderer();
	NPT_String tryGetDescriptionUrl(const char *uuid);
	void removeMRByUUID(const char *uuid);
	NPT_String setPlayingRenderer(const char *uuid, int displaynum);
	NPT_String setAVTransportURI(const char *uri, const char *didl);
	void setPlayState(const char *playstate);
	void setMuteState(bool mute);
	void setPlaySeek(NPT_String reltime);
	void setMediaVolume(int volume);
	void setTvPlayById(int channel_id);
    void bindDTVDevice(const char * mdevid,const char * ddevid,const char* userid,const char* passport);
	//-------------
	void OnGetPositionInfoResult(
		NPT_Result                res ,
		PLT_DeviceDataReference  &device ,
		PLT_PositionInfo         *info ,
		void                     *userdata );
	void tryGetPositionInfo();
	/*void OnGetTransportInfoResult(
	    NPT_Result                res ,
	    PLT_DeviceDataReference&  device ,
	    PLT_TransportInfo*        info ,
	    void*                     userdata );
	void tryGetTransportInfo();*/
	void OnGetMediaInfoResult(
		NPT_Result                res ,
		PLT_DeviceDataReference  &device ,
		PLT_MediaInfo            *info ,
		void                     *userdata );
	void tryGetMediaInfo();
	void OnGetVolumeResult(
		NPT_Result                res ,
		PLT_DeviceDataReference  &device ,
		const char               *channel ,
		NPT_UInt32				  volume ,
		void                     *userdata );
	void tryGetVolume();
	void OnGetChannelGroupIDResult(
        NPT_Result               res ,
        PLT_DeviceDataReference& device ,
    	const char*				 channelid,
	    void*                    userdata);
	void tryGetChannelGroupID();
	void OnGetChangePlayIDStateResult(
        NPT_Result               res ,
        PLT_DeviceDataReference& device ,
    	const char*				 state,
	    void*                    userdata); 
	void OnGetMuteResult(
        NPT_Result                res ,
        PLT_DeviceDataReference&  device ,
		const char*               channel ,
    	bool				  mute ,
	    void*                     userdata );
	void setMediaPair(const char * uuid, NPT_String deviceName, int displaynum, bool newpair);
	NPT_Result DoSearch(NPT_String uuid,NPT_String search_criteria, int start_index, int max_results,NPT_Array<PLT_MediaObject> *searchResults );
	NPT_Result DoBrowse(NPT_String uuid,NPT_Array<NPT_String> target_object_classes,bool metadata,NPT_Array<PLT_MediaObject> *browseResults );	 
	NPT_Result  BrowseByObjectIDAndObjectClass(
						PLT_DeviceDataReference &device, 
						NPT_Array<NPT_String> target_object_classes,
						NPT_String object_id,
						bool metadata,
						NPT_Array<PLT_MediaContainer>* mediaContainers,
						NPT_Array<PLT_MediaObject> *browseResults);
	ActionMessage BookOrRecordEvent(BookOrRecordEventInfo eventInfo);
	void DoBookOrRecordEvent(NPT_String uuid,BookOrRecordEventInfo eventInfo,ActionMessage & actionMessage);
private:
	const char *ChooseIDFromTable(PLT_StringMap &table);
	void        PopDirectoryStackToRoot(void);
	//NPT_Result  DoBrowse(const char *object_id = NULL, bool metdata = false);

	void        GetCurMediaServer(PLT_DeviceDataReference &server);
	void        GetCurMediaRenderer(PLT_DeviceDataReference &renderer);

	PLT_DeviceDataReference ChooseDevice(const NPT_Lock<PLT_DeviceMap> &deviceList, const char *uuid);

	// Command Handlers
	void    HandleCmd_scan(const char *ip);
	void    HandleCmd_getms();
	void    HandleCmd_setms();
	void    HandleCmd_ls();
	void    HandleCmd_info();
	void    HandleCmd_cd(const char *command);
	void    HandleCmd_cdup();
	void    HandleCmd_pwd();
	void    HandleCmd_help();
	void    HandleCmd_getmr();
	void    HandleCmd_setmr();
	void    HandleCmd_open();
	void    HandleCmd_play();
	void    HandleCmd_seek(const char *command);
	void    HandleCmd_stop();
	void    HandleCmd_mute();
	void    HandleCmd_unmute();

private:
	/* The tables of known devices on the network.  These are updated via the
	 * OnMSAddedRemoved and OnMRAddedRemoved callbacks.  Note that you should first lock
	 * before accessing them using the NPT_Map::Lock function.
	 */
	NPT_Lock<PLT_DeviceMap> m_MediaServers;
	NPT_Lock<PLT_DeviceMap> m_MediaRenderers;

	/* The currently selected media server as well as
	 * a lock.  If you ever want to hold both the m_CurMediaRendererLock lock and the
	 * m_CurMediaServerLock lock, make sure you grab the server lock first.
	 */
	PLT_DeviceDataReference m_CurMediaServer;
	NPT_Mutex               m_CurMediaServerLock;

	/* The currently selected media renderer as well as
	 * a lock.  If you ever want to hold both the m_CurMediaRendererLock lock and the
	 * m_CurMediaServerLock lock, make sure you grab the server lock first.
	 */
	PLT_DeviceDataReference m_CurMediaRenderer;
	NPT_Mutex               m_CurMediaRendererLock;

	/* the most recent results from a browse request.  The results come back in a
	 * callback instead of being returned to the calling function, so this
	 * global variable is necessary in order to give the results back to the calling
	 * function.
	 */
	PLT_MediaObjectListReference m_MostRecentBrowseResults;

	/* When browsing through the tree on a media server, this is the stack
	 * symbolizing the current position in the tree.  The contents of the
	 * stack are the object ID's of the nodes.  Note that the object id: "0" should
	 * always be at the bottom of the stack.
	 */
	NPT_Stack<NPT_String> m_CurBrowseDirectoryStack;

	/* the semaphore on which to block when waiting for a response from over
	 * the network
	 */
	NPT_SharedVariable m_CallbackResponseSemaphore;
};

void PltMediaControlSetUp();
void PltMediaControlSetUpAndIgnore(const char *ignoreuuid);
void PltMediaControlResearch();
void PltMediaControlStop();
PLT_SkMediaController* getMediaController();
#endif

